package JVM.第06篇_垃圾回收篇;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 强引用  软引用  弱引用  虚引用  终结器引用
 * 强引用:就算出现OOM也不会进行垃圾回收
 * 软引用:内存不足才回收
 *      软引用是用来描述一些还有用，但非必需的对象。
 *      只被软引用关联着的对象，在系统将要发生内存溢出异常前，
 *      会把这些对象列进回收范围之中进行第二次回收，如果这次回收还没有足够的内存，才会抛出内存溢出异常。
 *      软引用通常用来实现内存敏感的缓存。
 *      比如:高速缓存就有用到软引用。
 *      如果还有空闲内存，就可以暂时保留缓存，当内存不足时清理掉，
 *      这样就保证了使用缓存的同时，不会耗尽内存。
 *      垃圾回收器在某个时刻决定回收软可达的对象的时候，会清理软引用，
 *      并可选地把引用存放到一个引用队列( Reference Queue)。
 *      类似弱引用，只不过Java虚拟机会尽量让软引用的存活时间长一些， 迫不得已才清理。
 *
 * 弱引用:只要GC就回收
 *      弱引用也是用来描述那些非必需对象，
 *      只被弱引用关联的对象只能生存到下一次垃圾收集发生为止。
 *      在系统GC时，只要发现弱引用，不管系统堆空间使用是否充足，都会回收掉只被弱引用关联的对象。
 *      但是，由于垃圾回收器的线程通常优先级很低，因此，并不一定能很快地发现持有弱引用的对象。
 *      在这种情况下，弱引用对象可以存在较长的时间。
 *      弱引用和软引用一样，在构造弱引用时，也可以指定一个引用队列，
 *      当弱引用对象被回收时，就会加入指定的引用队列，通过这个队列可以跟踪对象的回收情况。
 *      弱引用非常适合来保存那些可有可无的缓存数据。如果这么做，当系统内存不足时，
 *      这些缓存数据会被回收，不会导致内存溢出。
 *      而当内存资源充足时，这些缓存数据又可以存在相当长的时间，从而起到加速系统的作用。
 *
 * 虚引用:形同虚设  必须和引用队列(ReferencesQueue)联合使用
 *       主要作用:跟踪对象被垃圾回收的状态
 *              仅仅提供了一种确保对象被finalize以后做的某些事情的机制
 *        get方法总是NULL
 *      虚引用(Phantom Reference) 一对象回收跟踪也称为“幽灵引用”或者“幻影引用”，
 *      是所有引用类型中最弱的一个。
 *      一个对象是否有虚引用的存在，完全不会决定对象的生命周期。
 *      如果一个对象仅持有虚引用，那么它和没有引用几乎是一样的，随时都可能被垃圾回收器回收。
 *      它不能单独使用，也无法通过虚引用来获取被引用的对象。
 *      当试图通过虚引用的get()方法取得对象时，总是null。
 *      为一个对象设置虚引用关联的唯一目的在于跟踪垃圾回收过程。
 *      比如:能在这个对象被收集器回收时收到一个系统通知。
 *
 *      ●虚引用必须和引用队列一起使用。虚引用在创建时必须提供一个引用队列作为参数。
 *      当垃圾回收器准备回收一个对象时， 如果发现它还有虚引用，就会在回收对象后，
 *      将这个虚引用加入引用队列，以通知应用程序对象的回收情况。
 *      ●由于虚引用可以跟踪对象的回收时间，因此，也可以将一些资源释放操作放置在虚引用中执行和记录。
 * 终结器引用(Final reference)
 *      ●它用以实现对象的finalize()方法， 也可以称为终结器引用。
 *      ●无需手动编码，其内部配合引用队列使用。
 *      ●在GC时，终结器引用入队。
 *      由Finalizer线 程通过终结器引用找到被引用对象并调用它的finalize()方法，第二次GC时才能回收被引用对象。
 */

public class I_强软弱虚终结器引用 {
    public static void main(String[] args) {

//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        SoftReference_NotEnough();

    }
    private static void PhantomReferenceDemo() {
        List o1=new ArrayList();
        o1.add(5);
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();//引用队列  在被GC垃圾回收后会有值
        WeakReference<Object> weakReference=new WeakReference<>(o1,referenceQueue);//弱引用
        PhantomReference<Object> phantomReference=new PhantomReference<>(o1,referenceQueue);//虚引用
        System.out.println(o1);//5
        System.out.println(weakReference.get());//5   弱引用   gc才会收
        System.out.println(phantomReference.get());//null   虚引用
        System.out.println(referenceQueue.poll());//null
        System.out.println("================");
        o1=null;//置为空
        System.gc();//垃圾回收
        try{TimeUnit.MILLISECONDS.sleep(100);}catch (InterruptedException e){ e.printStackTrace();}

        System.out.println(o1);//null
        System.out.println(weakReference.get());//null   弱引用 gc直接回收
        System.out.println(phantomReference.get());//null    虚引用 一直为空
        System.out.println(referenceQueue.poll());
        //java.lang.ref.WeakReference@66d3c617    垃圾回收将 弱引用的东西放入ReferenceQueue引用队列里
        System.out.println(referenceQueue.poll());
        //java.lang.ref.PhantomReference@63947c6b  垃圾回收将 虚引用放入ReferenceQueue引用队列里
        System.out.println(referenceQueue.poll());//null    只放入了两个
    } //虚引用

    private static void WeakHashMapDemo() {

        System.out.println("=========HashMap============");
        HashMap<Integer,String> map=new HashMap<>();
        Integer key1 = new Integer(1);
        String value1 = "HashMap";
        map.put(key1,value1);
        System.out.println(map);
        key1=null;
        System.out.println(map);
        System.gc();
        System.out.println(map);

        System.out.println("=========WeakHashMap============");
        WeakHashMap<Integer,String> weakHashMap=new WeakHashMap<>();
        Integer key2 = new Integer(1);

        String  value2 = "WeakHashMap";
        weakHashMap.put(key2,value2);
        System.gc();
        System.out.println(weakHashMap);
        key2=null;
        System.out.println(weakHashMap);
        System.gc();
        System.out.println(weakHashMap);
    }    //弱引用 GC直接回收
    private static void WeakReferenceDemo() {
        Object o1=new Object();
        WeakReference<Object> weakReference=new WeakReference<>(o1);
        System.out.println(o1);
        System.out.println(weakReference.get());
        o1=null;
        System.gc();
        System.out.println("================");
        System.out.println(o1);
        System.out.println(weakReference.get());//不管内存够不够  直接回收为空
    }  //弱引用 GC直接回收

    private static void SoftReference_Enough(){
        /**
         * 软引用在内存足的时候不回收
         */
        Object o1=new Object();
        SoftReference<Object> softReference=new SoftReference<>(o1);
        System.out.println(softReference.get());
        o1=null;
        System.gc();
        System.out.println(softReference.get());
    } //软引用在内存足的时候不回收

    private static void SoftReference_NotEnough() {
        /**
         * -Xms5m -Xmx5m -XX:+PrintGCDetails
         */
        Object o1=new Object();
        SoftReference<Object> softReference=new SoftReference<>(o1);
        System.out.println("初     始\t：" + softReference.get());
        o1=null;
        System.gc();
        System.out.println("正常   GC\t：" + softReference.get());
        try {
            byte[] bytes=new byte[5*1024*1024];
            System.gc();
        }catch (Throwable e){
            e.printStackTrace();
        }finally {
            //如果内存不足  也会输出null
            System.out.println("内存不足GC\t：" + softReference.get());
        }

    } //软引用在内存不足的时候回收


    private static void ReferenceDemo() {
        Object obj1=new Object();
        Object obj2=obj1;
        System.out.println(obj1);
        obj1=null;
        System.gc();
        System.out.println(obj1);//null
        System.out.println(obj2);//不影响
    }  //强引用

}
